/*
 * output.h
 *
 *  Created on: Jan 6, 2012
 *      Author: liuhaifeng
 */

#ifndef _FILTER_H_
#define _FILTER_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <defs.h>
#include <vars.h>
#include <dataset.h>
#include <expression.h>

static const char * filter_parse_condition(const char *str, Expression **exp) {
	str = exp_parse(exp, str, ':');
	return str;
}

static int ident_eval(char *ret, const char *ident, void *arg) {
	HttpLogInfo *info = (HttpLogInfo *)arg;

	if (strcmp(ident, "h") == 0) {
		sprintf(ret, "%u.%u.%u.%u",
				info->logEntry.ip.parts.a,
				info->logEntry.ip.parts.b,
				info->logEntry.ip.parts.c,
				info->logEntry.ip.parts.d);
	} else if (strcmp(ident, "i") == 0) {
		strncpy(ret, info->logEntry.identity, EXP_MAX_STRING);
	} else if (strcmp(ident, "u") == 0) {
		strncpy(ret, info->logEntry.userid, EXP_MAX_STRING);
	} else if (strcmp(ident, "t") == 0) {
		sprintf(ret, "%04u-%02u-%02u %02u:%02u:%02u",
				info->logEntry.time.year,
				info->logEntry.time.month + 1,
				info->logEntry.time.date,
				info->logEntry.time.hour,
				info->logEntry.time.minute,
				info->logEntry.time.second);
	} else if (strcmp(ident, "ty") == 0) {
		sprintf(ret, "%04u", info->logEntry.time.year);
	} else if (strcmp(ident, "tM") == 0) {
		sprintf(ret, "%02u", info->logEntry.time.month + 1);
	} else if (strcmp(ident, "td") == 0) {
		sprintf(ret, "%02u", info->logEntry.time.date);
	} else if (strcmp(ident, "tH") == 0) {
		sprintf(ret, "%02u", info->logEntry.time.hour);
	} else if (strcmp(ident, "tm") == 0) {
		sprintf(ret, "%02u", info->logEntry.time.minute);
	} else if (strcmp(ident, "ts") == 0) {
		sprintf(ret, "%02u", info->logEntry.time.second);
	} else if (strcmp(ident, "tz") == 0) {
		sprintf(ret, "%c %02u%02u",
				info->logEntry.time.tz_flag == TZ_FLAG_WEST ? '-' : '+',
				info->logEntry.time.tz_hour, info->logEntry.time.tz_minute);
	} else if (strcmp(ident, "tzf") == 0) {
		sprintf(ret, "%c", info->logEntry.time.tz_flag == TZ_FLAG_WEST ? '-' : '+');
	} else if (strcmp(ident, "tzh") == 0) {
		sprintf(ret, "%02u", info->logEntry.time.tz_hour);
	} else if (strcmp(ident, "tzm") == 0) {
		sprintf(ret, "%02u", info->logEntry.time.tz_minute);
	} else if (strcmp(ident, "m") == 0) {
		strncpy(ret, info->logEntry.method, EXP_MAX_STRING);
	} else if (strcmp(ident, "l") == 0) {
		strncpy(ret, info->logEntry.url, EXP_MAX_STRING);
	} else if (strcmp(ident, "lp") == 0) {
		strncpy(ret, info->logEntry.uri.path, EXP_MAX_STRING);
	} else if (strcmp(ident, "la") == 0) {
		strncpy(ret, info->logEntry.uri.anchor, EXP_MAX_STRING);
	} else if (strcmp(ident, "p") == 0) {
		strncpy(ret, info->logEntry.protocol, EXP_MAX_STRING);
	} else if (strcmp(ident, "s") == 0) {
		sprintf(ret, "%u", info->logEntry.status);
	} else if (strcmp(ident, "b") == 0) {
		sprintf(ret, "%u", info->logEntry.bytes);
	} else if (strcmp(ident, "r") == 0) {
		strncpy(ret, info->logEntry.referer, EXP_MAX_STRING);
	} else if (strcmp(ident, "a") == 0) {
		strncpy(ret, info->logEntry.user_agent, EXP_MAX_STRING);
	} else {
		// TODO give other modules the chance to explain there identity.
		return -1;
	}
	return 0;
}

static int func_eval(char *ret, ExpFunction *func, IdentEval ident_eval,
		void *arg) {
	HttpLogInfo *info = (HttpLogInfo *)arg;
	Expression *param;
	char *str;

	if (strcmp(func->name, "P") == 0) {
		if (count_list(func->parameters) != 1)
			return -1;
		param = head(func->parameters);
		str = NULL;
		if (param->type == EXP_IDENTITY)
			str = param->exp.ident;
		else if (param->type == EXP_CONSTANT)
			str = param->exp.constant;
		else
			return -1;
		if (info->logEntry.uri.params != NULL)
			str = (char *) get(info->logEntry.uri.params, str);
		if (str != NULL)
			strncpy(ret, str, EXP_MAX_STRING);
		else
			ret[0] = 0;
	} else {
		// TODO give the chance to modules which supply function(s).
		return -1;
	}
	return 0;
}

static BOOL filter_check(HttpLogInfo *logInfo, Expression *exp) {
	BOOL ret;

	if (exp == NULL) {
		return TRUE;
	}

	if (exp_eval(&ret, exp, ident_eval, func_eval, logInfo) != 0) {
		fputs("Failed to evaluate expression.\n", stderr);
		return FALSE;
	}
	return ret;
}

#endif /* _FILTER_H_ */
